package com.v9.system.controller;

import cn.hutool.core.util.RandomUtil;
import com.v9.common.config.AppConfig;
import com.v9.common.dto.MenuTreeDto;
import com.v9.common.dto.MenuTypeEnum;
import com.v9.common.dto.UserDto;
import com.v9.common.model.FunResTypeEnum;
import com.v9.common.tools.RandImageUtil;
import com.v9.common.utils.StringUtils;
import com.v9.common.web.AbstractController;
import com.v9.system.domain.MenuInfo;
import com.v9.system.service.MenuInfoService;
import com.v9.system.service.UserInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@RestController
@Tag(name = "登录")
@Slf4j
@RequestMapping(value = "/", method = RequestMethod.POST)
public class LoginController extends AbstractController {

    @Resource
    private AppConfig appConfig;
    @Resource
    private UserInfoService userInfoService;

    @Resource
    private MenuInfoService menuInfoService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    private final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";

    @Resource
    private MenuInfoService permissionInfoService;

    @Operation(summary = "登录")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Map<String, Object> login(@RequestBody LoginDto dto, HttpServletResponse response) {
        return buildMessage(() -> {
//            String cacheKey= MessageFormat.format("login:code:{0}",dto.getKey());
//            String s = stringRedisTemplate.opsForValue().get(cacheKey);
//            if(StringUtils.isBlank(s)){
//                throw new BizException("data.error","验证码错误");
//            }
//            if(!s.equals(dto.getCode())){
//                throw new BizException("data.error","验证码错误");
//            }
            UserDto userDto = userInfoService.login(dto.getUsername(), dto.getPassword());
            String token = jwtTokenUtils.createToken(userDto);
            putCookie("token", token, response);
            Map<String, Object> results = new HashMap<>();
            results.put("token", token);
            return results;
        });
    }


    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public Map<String, Object> getInfo() {
        return buildMessage(() -> {
            UserDto user = getUser();
            Set<String> roles = user.getRoles();
            roles.add("admin");
            List<MenuInfo> menuInfos = menuInfoService.queryAll();
            List<String> collect = menuInfos.stream().map(MenuInfo::getPerms).collect(Collectors.toList());
            Set<String> permissions = user.getPermissions();
            permissions.add("*:*:*");
            Map<String, Object> results = new HashMap<>();
            results.put("user", user);
            results.put("roles", roles);
            results.put("permissions", collect);
            return results;
        });
    }


    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public Map<String, Object> getRouters() {
        return buildMessage(() -> {
            List<MenuInfo> menuInfos = null;
            if (getUser().getIsAdmin()) {
                menuInfos = menuInfoService.queryAll();
            } else {
                menuInfos = menuInfoService.queryByPin(getUser().getPin());
            }
            List<MenuInfo> collect = menuInfos.stream().filter(item -> item.getMenuType() != MenuTypeEnum.F).collect(Collectors.toList());
            List<MenuTreeDto> menus = menuInfoService.buildTreeByList(collect);
            return menuInfoService.buildMenus(menus);
        });
    }
    /**
     * 构建前端路由所需要的菜单
     *
     * @param menus 菜单列表
     * @return 路由列表
     */

    @Operation(summary = "登出")
    @RequestMapping(value = "/logout")
    public void exit() {
        String token = getToken();
        if (StringUtils.isBlank(token)) {
            return;
        }
        userInfoService.exit(token);
    }


    /**
     * 后台生成图形验证码 ：有效
     *
     * @param response
     */
    @Operation(summary = "获取验证码")
    @GetMapping(value = "captchaImage")
    public LoginVDataDto randomImage(HttpServletResponse response) throws IOException {
        String uuid = StringUtils.getUUID();
        String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);
        String lowerCaseCode = code.toLowerCase();
        String cacheKey = MessageFormat.format("login:code:{0}", uuid);
        stringRedisTemplate.opsForValue().set(cacheKey, lowerCaseCode, 60, TimeUnit.SECONDS);
        String generate = RandImageUtil.generate(code);
        LoginVDataDto result = new LoginVDataDto();
        result.setImage(generate);

        result.setUuid(uuid);
        return result;
    }


    @Data
    public static final class LoginDto {
        private String username;
        private String password;
        private String code;
        private String key;
    }

    @Data
    public static final class LoginVDataDto {
        String image;
        String uuid;
    }

    @Data
    public static class UserFunResResultDto {
        @Schema(description = "名称")
        private String name;
        @Schema(description = "上级功能")
        private Long parentId;
        @Schema(description = "标题")
        private String title;
        @Schema(description = "图标")
        private String icon;
        @Schema(description = "类型")
        private FunResTypeEnum funResType;
        private List<UserFunResResultDto> children;
    }
}
